//Headers from this project
#include "Stroustrup_5.h"

//Headers from standard libraries
#include <iostream>
#include <cassert>
#include <vector>


Stroustrup_5::Stroustrup_5()
{
}

Stroustrup_5::~Stroustrup_5()
{
}

void Stroustrup_5::run()
{
	std::cout << "Testing the simple pointer to char..." << std::endl;
	test_of_simple_pointer();
	std::cout << "Testing arrays..." << std::endl;
	testing_arrays();
	std::cout << "Testing of arrays initialization..." << std::endl;
	testing_initialization_of_arrays();
	std::cout << "Testing of string literals..." << std::endl;
	testing_string_literals();
	std::cout << "Testing of pointers to arrays..." << std::endl;
	testing_pointers_to_arrays();
}

void Stroustrup_5::test_of_simple_pointer()
{
	char c = 'a';
	char* p = &c;
	char c2 = *p;
	std::cout << "The value of *p is " << *p << std::endl;
	std::cout << "The size of pointer is " << sizeof(p) << 
		" because it stores an address, which is of integer type" << std::endl;
 }

void Stroustrup_5::testing_arrays()
{
	const int n = 3;
	const int m = 5;
	float v[n];
	float x = 0.0;
	for (int i = 0; i < n; ++i) {
		x += i;
		v[i] = x;
		std::cout << "The " << i << " element value from array of floats is " << v[i] << std::endl;
	}
	std::cout << std::endl;
	char* a[m];
	char c = 'a';
	for (int i = 0; i < m; ++i) {
		a[i] = &c + i;
		std::cout << "The symbol in " << i << " address beginning from address c is " 
			<< *a[i] <<std::endl;
	}
	
}

void Stroustrup_5::testing_initialization_of_arrays()
{
	int array1[] = {1, 2, 3, 4};
	std::cout << "The size of array in case of it is not given"
		" and defined by initialization list is " << sizeof(array1)/sizeof(int) << std::endl;
	std::cout << "The assignment not allowed. Compile ERROR!!!" << std::endl;
	std::cout << "The size of array initialization list should be <= "
		"of given size for array. Compile ERROR!!!!" << std::endl;
	int array2[7] = {2, 4, 5};
	for (int i = 0; i < 7; ++i) {
		std::cout << array2[i] << "\t";
	}
	std::cout << std::endl;
	const int n = 2;
	const int m = 3;
	int variable_size = 6;
	std::vector<int> v2(variable_size);
	std::cout << "The size of vector can be variable, which differs from array. \n"
		"The size of vector is : "<< v2.size() << std::endl;
	int matrix[n][m] = {{15, 57, 7}, {5, 45, 13}}; // or it can be just {15, 57, 7, 5, 45, 13}
	for (int i = 0; i < n; ++i) {
		std::cout << std::endl;
		for (int j = 0; j < m; ++j) {
			std::cout << matrix[i][j]  << "\t";
		}
	}
	std::cout << std::endl;
}

static char* return_string_literal() 
{
	return "Out of called function";
}

void Stroustrup_5::testing_string_literals()
{
	std::cout << "The type of string literal is const char[sizeof(string_literal)] " << std::endl;
	char* p = "Platon";
	std::cout << "The size of \""<< p <<"\" string literal is " << sizeof(p) << std::endl;
	std::cout << "size of Platon is " << sizeof("Platon") << std::endl;
	std::cout << "The dereferenced pointer to literal is : " << *p << std::endl;
	//p[1] = '3'; not allowed, unexpected result
	char arr[] = "Zenon";
	std::cout << "The array with string value : " << arr << std::endl;
	arr[0] = 'R';
	std::cout << "The array with string value after first element modification : " <<
		arr << std::endl;
	p = return_string_literal();
	std::cout << "The returned string literal of function is : " << p << std::endl; 

	const char* q1 = "Hercules";
	const char* q2 = "Hercules";
	if (q1 == q2) {
		std::cout << "The literals with the same values are stored in the same place. "
			"Implementation dependent!!!"  << std::endl;
	}
	char* empty_string = ""; 
	std::cout << "The type of empty string is const char[1] " << std::endl;
	std::cout << "Grig\000oryan" << 
		"  --- Because the string literal always ends with \0 symbol" << std::endl;
	char cp[40];
	strcpy(cp, "Grig\000aaaa");
	std::cout << "Result of strcpy is " << cp << std::endl;
}

void Stroustrup_5::testing_pointers_to_arrays()
{
	char v[] = {1, 2, 3, 4};
	char* p = v;
	std::cout << p << std::endl;

	char v1[] = {'1', '2', '3', '4'};
	char* p1 = v1;
	std::cout << p1 << std::endl;
}


